#include "telnetwindow.h"
#include "ui_telnetwindow.h"
#include <QApplication>
#include <QShortcut>
#include <QPushButton>
#include <QLabel>
#include <QLayout>
#include <QKeyEvent>
#include <QScrollBar>
#include <QTime>
#include <QMessageBox>
#include <QTimer>
#include <QFont>
#include <QtTelnet>
#include <QThread>

#include <QInputDialog>
#include <QFileDialog>

LoginDialog::LoginDialog(QWidget *parent)
    : QDialog(parent)
{
    QGridLayout *gl = new QGridLayout;
    setLayout(gl);

    QLabel *l;

    l = new QLabel("&Login:", this);
    gl->addWidget(l, 0, 0);
    lle = new QLineEdit(this);
    gl->addWidget(lle, 0, 1);
    l->setBuddy(lle);

    l = new QLabel("&Password:", this);
    gl->addWidget(l, 1, 0);
    ple = new QLineEdit(this);
    ple->setEchoMode(QLineEdit::Password);
    gl->addWidget(ple, 1, 1);
    l->setBuddy(ple);

    QWidget *hbox = new QWidget(this);
    QHBoxLayout *hboxlayout = new QHBoxLayout;

    gl->addWidget(hbox, 2, 0, 1, 2);

    QPushButton *pb;
    pb = new QPushButton("&Ok");
    connect(pb, &QPushButton::clicked, this, &LoginDialog::accept);
    hboxlayout->addWidget(pb);

    pb = new QPushButton("&Cancel");
    connect(pb, &QPushButton::clicked, this, &LoginDialog::reject);
    hboxlayout->addWidget(pb);

    hbox->setLayout(hboxlayout);
}

LoginDialog::~LoginDialog()
{
    delete lle;
    delete ple;
}

QString LoginDialog::login() const
{
    return lle->text();
}

QString LoginDialog::password() const
{
    return ple->text();
}

TelnetWindow::TelnetWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::TelnetWindow),
    telnet(new QtTelnet)
{
    ui->setupUi(this);

    connect(ui->quitBtn, &QPushButton::clicked, this, &TelnetWindow::close);

    QShortcut *shortcut;

    shortcut = new QShortcut(this);
    shortcut->setKey(Qt::CTRL + Qt::Key_D);
    connect(shortcut, &QShortcut::activated, this, &TelnetWindow::deleteCharOrLogout);

    shortcut = new QShortcut(this);
    shortcut->setKey(Qt::CTRL + Qt::Key_Z);
    connect(shortcut, &QShortcut::activated, this, &TelnetWindow::suspend);

    shortcut = new QShortcut(this);
    shortcut->setKey(Qt::CTRL + Qt::Key_C);
    connect(shortcut, &QShortcut::activated, this, &TelnetWindow::kill);

    ui->context->setReadOnly(true);

    connect(ui->cmdLine, &QLineEdit::returnPressed, this, &TelnetWindow::lineReturnPressed);
    connect(telnet, &QtTelnet::message, this, &TelnetWindow::telnetMessage);
    connect(telnet, &QtTelnet::loginRequired, this, &TelnetWindow::telnetLoginRequired);
    connect(telnet, &QtTelnet::loginFailed, this, &TelnetWindow::telnetLoginFailed);
    connect(telnet, &QtTelnet::loggedIn, this, &TelnetWindow::telnetLoggedIn);
    connect(telnet, &QtTelnet::loggedOut, this, &TelnetWindow::telnetLoggedOut);
    connect(telnet, &QtTelnet::connectionError, this, &TelnetWindow::telnetConnectionError);
}

TelnetWindow::~TelnetWindow()
{
    delete ui;
}

void TelnetWindow::telnetMessage(const QString &msg)
{
    ui->context->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
    ui->context->insertPlainText(stripCR(msg));
//    qDebug() << msg.toLatin1().toHex(' ');
//    qDebug() << stripCR(msg).toLatin1().toHex(' ');
//    qDebug() << ui->context->toPlainText().toLatin1().toHex(' ');
//    if( msg == "am335x-evm login: ")
//    {
//        telnet->sendData("root\r\n");
//    }
//    if( (msg.contains("root@am335x-evm:~# ",Qt::CaseSensitive)) )
//    {
//        telnet->sendData("update-unpack /run/media/sda1/Software-1.upd;sleep 3;"
//                    "update-unpack /run/media/sda1/Software-1.upd\r\n");
//        i++;
//    }
//    if(i == 2)
//    {
//        QMessageBox::information(NULL,"title","程序运行完成！",QMessageBox::Ok);
//        QTimer::singleShot(0, qApp, SLOT(quit()));
//    }
    QScrollBar *s = ui->context->verticalScrollBar();
    s->setValue(s->maximum());
}

void TelnetWindow::telnetLoginRequired()
{
    LoginDialog ld(this);
    if (ld.exec() == LoginDialog::Accepted) {
        telnet->login(ld.login(), ld.password());
        telnet->sendData("root\r\n");
    } else {
        telnet->logout();
    }
}

void TelnetWindow::telnetLoginFailed()
{

}

void TelnetWindow::telnetLoggedOut()
{

}

void TelnetWindow::telnetLoggedIn()
{

}

void TelnetWindow::telnetConnectionError(QAbstractSocket::SocketError error)
{
    switch (error) {
    case QAbstractSocket::SocketTimeoutError:
        QMessageBox::information(this, "Error", "连接失败！", QMessageBox::Ok);
        break;
    default:
        break;
    }
}

void TelnetWindow::deleteCharOrLogout()
{
    if (ui->cmdLine->text().isEmpty()) {
        telnet->logout();
    } else {
        int cpos = ui->cmdLine->cursorPosition();
        QString txt = ui->cmdLine->text();
        if (cpos < (int)txt.length()) {
            ui->cmdLine->setText(txt.remove(cpos, 1));
            ui->cmdLine->setCursorPosition(cpos);
        }
    }
}

void TelnetWindow::suspend()
{
    telnet->sendControl(QtTelnet::Suspend);
}

void TelnetWindow::kill()
{
    telnet->sendControl(QtTelnet::InterruptProcess);
}

void TelnetWindow::lineReturnPressed()
{
    telnet->sendData(ui->cmdLine->text()+QString("\r\n"));
    ui->cmdLine->clear();
}

QString TelnetWindow::stripCR(const QString &msg)
{
    QString nmsg(msg);
    nmsg.remove('\r');
    nmsg.remove(QRegExp("\033\\[[0-9;]*[A-Za-z]")); // Also remove terminal control codes
    return nmsg;
}

void TelnetWindow::resizeEvent(QResizeEvent *event)
{
    QFontMetrics fm(font());
    int lh = fm.lineSpacing();
    int cw = fm.horizontalAdvance(QChar('X'));
    QRect r = ui->context->visibleRegion().boundingRect();
    int dx = event->oldSize().width() - r.width();
    int dy = event->oldSize().height() - r.height();

    telnet->setWindowSize((event->size().width() - dx) / cw,
                     (event->size().height() - dy) / lh);
}

bool TelnetWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::ShortcutOverride) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        if (ke->modifiers() & Qt::ControlModifier) {
            switch (ke->key()) {
            case Qt::Key_C:
            case Qt::Key_D:
            case Qt::Key_Z:
                return true;
            default:
                break;
            }
        }
    }
    return QObject::eventFilter(obj, event);
}

void TelnetWindow::on_connectBtn_clicked()
{
    if (telnet->socket()->state() == QTcpSocket::ConnectedState) {
        telnet->close();
        ui->connectBtn->setText(QString("Connect"));
        return;
    }
    QString host = ui->host->text();
    QString user = ui->username->text();
    QString pw = ui->password->text();

    host = host.trimmed();
    if (!host.isEmpty())
    {
        telnet->connectToHost(host);
        if (telnet->socket()->state() == QTcpSocket::ConnectedState) {
            if (!user.isEmpty()) {
                QThread::msleep(100);
                telnet->sendData(user + "\r\n");
                telnet->socket()->flush();
                if (!pw.isEmpty()) {
                    QThread::msleep(100);
                    telnet->sendData(pw + "\r\n");
                    telnet->socket()->flush();
                }
            }

            ui->connectBtn->setText(QString("Disconnect"));
        }
    }
    else
    {
        ui->context->setPlainText("Not connected");
        QMessageBox::information(this, "Warning", "Host 不能为空！", QMessageBox::Ok);
    }
}

void TelnetWindow::on_loadBtn_clicked()
{
    QString filename = QFileDialog::getOpenFileName(this,
                                                    "Load Script File",
                                                    "./");
    if (filename.isEmpty()) return;

    QFileInfo fi;

    fi.setFile(filename);

    ui->scriptFile->setText(fi.absoluteFilePath());
}

void TelnetWindow::on_execBtn_clicked()
{
    if (ui->scriptFile->text().isEmpty()) {
        QMessageBox::information(this, "Warning","脚本文件不能为空！",QMessageBox::Ok);
        return;
    }

    uint interval = 1;
    if (ui->interval->text().isEmpty()) {
        interval = 1000;
        ui->interval->setText("1000");
    } else {
        interval = ui->interval->text().toUInt();
    }

    QFile fil;
    fil.setFileName(ui->scriptFile->text());

    if (fil.open(QFile::ReadOnly)) {
        do {
            QByteArray line = fil.readLine(1024);
            if (line.isEmpty()) break;
            if (line.startsWith("#")) continue;
            scripts.append(line);
        } while (1);
    }

    ui->execBtn->setEnabled(false);
    ui->pauseBtn->setEnabled(true);
    ui->stopBtn->setEnabled(true);

    script_timer = new QTimer;
    script_timer->setInterval(interval);
    connect(script_timer, &QTimer::timeout, this, &TelnetWindow::execScript);
    script_timer->start();

    execScript();
}

void TelnetWindow::on_pauseBtn_clicked()
{
    if (script_timer == nullptr) return;

    if (script_timer->isActive()) {
        script_timer->stop();
    } else {
        script_timer->start();
        execScript();
    }
}

void TelnetWindow::on_stopBtn_clicked()
{
    script_timer->stop();
    disconnect(script_timer, &QTimer::timeout, this, &TelnetWindow::execScript);
    delete script_timer;
    script_timer = nullptr;

    scripts.clear();

    ui->execBtn->setEnabled(true);
    ui->pauseBtn->setEnabled(false);
    ui->stopBtn->setEnabled(false);
}

void TelnetWindow::execScript()
{
    QByteArray cmd;

    if (scripts.isEmpty()) {
        on_stopBtn_clicked();
        return;
    }

    cmd = scripts.takeFirst();

    telnet->sendData(cmd + "\r\n");

    if (scripts.isEmpty()) {
        on_stopBtn_clicked();
        return;
    }
}
